package com.sort;

import com.list.OrderedList;

/**
 * 桶排序:
 * 计数排序适合小范围的大量重复元素,而桶排序适合区间内尽可能随机的元素
 * 它的思想是:
 * 把数据存在的区间划分为小的区间,然后将这些数据在小区间内排好序,再合并成排序后的元素
 */
public class BucketSort {
    public static int[] bucketSort(int[] arr) {
        //找到最大值与最小值,得到分布的区间
        int min = arr[0];
        int max = arr[0];
        for (int anArr : arr) {
            if (anArr > max) {
                max = anArr;
            } else if (anArr < min) {
                min = anArr;
            }
        }
        //得到最大值后,就可以划分区间了,这里我把它分为10个区间
        int part = 10;
        //这里对step进行改造,防止数组下标越界
        while ((max - min) % part != 0) {
            max += 1;
        }
        int step = (max - min) / part;
        return bucketSort(arr, step, part);
    }

    private static int[] bucketSort(int[] arr, int step, int part) {
        OrderedList[] lists = new OrderedList[part];  //开辟新的数组空间,用来保存链表
        for (int i = 0; i < arr.length; i++) {
            lists[i] = new OrderedList();
        }
        //现在开始遍历整个待排数组,并且把它们有序的排在 lists 中
        for (int anArr : arr) {
            lists[anArr / step].insert(anArr);
        }
        //输出
        int index = 0;
        int[] resultArr = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            int count = lists[i].getCount();
            for (int j = 0; j < count; j++) {
                resultArr[index] = lists[i].popFirst();
                index++;
            }
        }
        return resultArr;
    }
}
